home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / ARGONET / PD / FILER / X-FILES.ZIP / 057 / !X-Files / c / compact < prev    next >
Text File  |  1996-04-22  |  6KB  |  197 lines

  1. /* compact.c - Compaction routine triggered when the wasted space in an image
  2.  *             gets above 10%
  3.  */
  4.  
  5. #include "chunks.h"
  6. #include "debug.h"
  7. #include <stdlib.h>
  8. #include "swis.h"
  9.  
  10. #define BATCHSIZE  100
  11.  
  12. #define _max(x, y) ((x) > (y) ? (x) : (y))
  13. #define _min(x, y) ((x) < (y) ? (x) : (y))
  14.  
  15. typedef struct
  16. {
  17.    unsigned cnkNum;
  18.    xFiles_chunk chunk;
  19.  
  20. } xFiles__chunkRef;
  21.  
  22. /* Yet another dodgy implementation of my standard shifting heap
  23.  * compactor. Each pass finds the chunk numbers of the next N items
  24.  * in the file, then relocates them down towards the header. Simple
  25.  * as that.
  26.  */
  27.  
  28. _kernel_oserror *xFiles_Compact(xFiles_info *pInfo)
  29. {
  30.    _kernel_oserror *err;
  31.    xFiles__chunkRef *workSpace = NULL;
  32.    unsigned tableSize, bitSize, nChunks, fileSize;
  33.    unsigned thisChunk;
  34.    unsigned highWaterMark = xFiles_roundUp(pInfo, sizeof(xFiles_header));
  35.    unsigned tablePos;
  36.    xFiles_chunk *pChunk;
  37.    int workUsed = 0;
  38.    int i;
  39.    _kernel_swi_regs regs;
  40.  
  41.    if (pInfo->compacting)
  42.       return NULL;
  43.  
  44.    pInfo->compacting = TRUE;
  45.    (void) _kernel_swi(Hourglass_On, ®s, ®s);
  46.  
  47.    if (err = xFiles_getLength(pInfo, &fileSize), err) goto fail;
  48.  
  49.    /*TRACE("Compacting file (size = %08x)\n", fileSize);*/
  50.  
  51.    if (workSpace = malloc(BATCHSIZE * sizeof(xFiles__chunkRef)), !workSpace)
  52.    {
  53.       err = &xFiles_NoMemory;
  54.       goto fail;
  55.    }
  56.  
  57.    do
  58.    {
  59.       /* Collect the next 100 candidates */
  60.  
  61.       tableSize = pInfo->fileHeader.chunkTable.size;
  62.       tablePos = 0;
  63.       workUsed = 0;
  64.       thisChunk = 0;
  65.  
  66.       if (err = xFiles_claimBuffer(tableSize), err)
  67.          goto fail;
  68.  
  69.       while (tableSize > 0)
  70.       {
  71.          bitSize = _min(tableSize, xFiles_windowBufferSize);
  72.          nChunks = bitSize / sizeof(xFiles_chunk);
  73.          bitSize = nChunks * sizeof(xFiles_chunk);
  74.  
  75.          if (err = xFiles_readChunk(pInfo, xFiles_windowBuffer, 0, tablePos, bitSize), err)
  76.             goto fail2;
  77.  
  78.          for (pChunk = xFiles_windowBuffer; nChunks > 0; nChunks--, pChunk++, thisChunk++)
  79.          {
  80.             if (pChunk->usage != 0x45455246 && pChunk->offset >= highWaterMark)
  81.             {
  82.                xFiles__chunkRef ref, tmp;
  83.  
  84.                ref.cnkNum  = thisChunk;
  85.                ref.chunk   = *pChunk;
  86.  
  87.                for (i = 0; i < workUsed; i++)
  88.                {
  89.                   if (ref.chunk.offset < workSpace[i].chunk.offset)
  90.                   {
  91.                      tmp = workSpace[i];
  92.                      workSpace[i] = ref;
  93.                      ref = tmp;
  94.                   }
  95.                }
  96.  
  97.                if (workUsed < BATCHSIZE)
  98.                   workSpace[workUsed++] = ref;
  99.             }
  100.          }
  101.  
  102.          tableSize -= bitSize;
  103.          tablePos  += bitSize;
  104.       }
  105.  
  106.       if (err = xFiles_releaseBuffer(), err)
  107.          goto fail;
  108.  
  109.       /*TRACE("Identified %d chunks\n", workUsed);
  110.  
  111.       for (i = 0; i < workUsed; i++)
  112.       {
  113.          TRACE("chunk %5d at %08x, size %08x, allocSize %08x\n",
  114.                   workSpace[i].cnkNum, workSpace[i].chunk.offset,
  115.                   workSpace[i].chunk.size, workSpace[i].chunk.allocSize);
  116.       }*/
  117.  
  118.       /* Processed the whole table and got a few candidates for relocating, so let's
  119.        * shift them.
  120.        */
  121.  
  122.       for (i = 0; i < workUsed; i++)
  123.       {
  124.          if (workSpace[i].chunk.allocSize != xFiles_roundDown(pInfo, workSpace[i].chunk.allocSize))
  125.             TRACE("How strange: allocSize = %08x\n", workSpace[i].chunk.allocSize);
  126.  
  127.          if (workSpace[i].chunk.allocSize < xFiles_roundUp(pInfo, workSpace[i].chunk.size))
  128.             TRACE("How odd: allocSize = %08x, size = %08x\n",
  129.                     workSpace[i].chunk.allocSize, workSpace[i].chunk.size);
  130.  
  131.          if (workSpace[i].chunk.offset != xFiles_roundDown(pInfo, workSpace[i].chunk.offset))
  132.             TRACE("How weird: offset = %08x\n", workSpace[i].chunk.offset);
  133.  
  134.          ASSERT(workSpace[i].chunk.allocSize >= workSpace[i].chunk.size);
  135.          ASSERT(workSpace[i].chunk.offset    >= sizeof(xFiles_header));
  136.  
  137.          workSpace[i].chunk.allocSize = xFiles_roundUp(pInfo, workSpace[i].chunk.size);
  138.  
  139.          /*TRACE("Moving %08x bytes from %08x to %08x\n",
  140.                        workSpace[i].chunk.allocSize, workSpace[i].chunk.offset, highWaterMark);*/
  141.  
  142.          if (workSpace[i].chunk.offset < highWaterMark && workSpace[i].chunk.allocSize != 0)
  143.          {
  144.             TRACE("*** can't move block from %08x to %08x\n",
  145.                        workSpace[i].chunk.offset, highWaterMark);
  146.             goto skip;           
  147.          }
  148.  
  149.          regs.r[0] = 100 * (workSpace[i].chunk.offset >> 8) / (fileSize >> 8);
  150.          (void) _kernel_swi(Hourglass_Percentage, ®s, ®s);
  151.  
  152.          if (err = xFiles_moveBlock(pInfo, highWaterMark, workSpace[i].chunk.offset, workSpace[i].chunk.allocSize), err)
  153.             goto fail;
  154.  
  155.          workSpace[i].chunk.offset = highWaterMark;
  156.  
  157.          if (err = xFiles_setChunkInfo(pInfo, workSpace[i].cnkNum, &workSpace[i].chunk), err)
  158.             goto fail;
  159.  
  160. skip:
  161.          highWaterMark += workSpace[i].chunk.allocSize;
  162.  
  163.          if (xFiles_roundDown(pInfo, highWaterMark) != highWaterMark)
  164.          {
  165.             TRACE("Huh? HWM = %08x\n", highWaterMark);
  166.          }
  167.       }
  168.  
  169.    } while (workUsed == BATCHSIZE);
  170.  
  171.    free(workSpace);
  172.  
  173.    /*TRACE("Compacted file (size = %08x)\n", highWaterMark);*/
  174.  
  175.    if (err = xFiles_setLength(pInfo, highWaterMark), err)
  176.       goto fail;
  177.  
  178.    pInfo->fileHeader.waste = 0;
  179.    if (err = xFiles_updateHeader(pInfo), err)
  180.       goto fail;
  181.  
  182.    pInfo->flags |= xFiles_fNeedTruncate;
  183.  
  184.    (void) _kernel_swi(Hourglass_Off, ®s, ®s);
  185.    pInfo->compacting = FALSE;
  186.    return err;
  187.  
  188. fail2:
  189.    (void) xFiles_releaseBuffer();
  190.  
  191. fail:
  192.    if (workSpace) free(workSpace);
  193.    pInfo->compacting = FALSE;
  194.    (void) _kernel_swi(Hourglass_Off, ®s, ®s);
  195.    return err;
  196. }
  197.